package JUC.synchronizedKeyword;

import java.util.Scanner;
import java.util.concurrent.TimeUnit;

/**
 * @className: SynchronizedDifferenceScope
 * @Description:
 * @Author: wangyifei
 * @Date: 2022/9/7 15:00
 */
public class SynchronizedDifferenceScope {
    public static class Car extends Abs{
        public synchronized static void move(){
            System.out.println("move start");
            working();
            System.out.println("move end");
        }

        public synchronized static void stop(){
            System.out.println("stop start");
            working();
            System.out.println("stop end");
        }
        public static void watchTV(){
            synchronized (Car.class){
                System.out.println("watchTV start");
                working();
                System.out.println("watchTV end");
            }
        }
        public void race(){
            synchronized (this){
                System.out.println("race start");
                working();
                System.out.println("race end");
            }
        }
        public synchronized void fire(){
            System.out.println("fire start");
            working();
            System.out.println("fire end");
        }
    }
    public static abstract class Abs{
        public static void working(){
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void invokerStaticMethod(){
        Thread t1 = new Thread(()->{
            Car.move();
        });
        Thread t2 = new Thread(()->{
            Car.stop();
        });
        t2.start();
        t1.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void invokerStaticBlock(){
        Thread t1 = new Thread(()->{
            Car.move();
        });
        Thread t2 = new Thread(()->{
            Car.watchTV();
        });
        t2.start();
        t1.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void invokerObjectMethod(){
        Car car = new Car();
        Thread t1 = new Thread(()->{
            car.move();
        });
        Thread t2 = new Thread(()->{
            car.stop();
        });
        t2.start();
        t1.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void invokerStaticAndObjectMethod(){
        Car car = new Car();
        Thread t1 = new Thread(()->{
            car.move();
        });
        Thread t2 = new Thread(()->{
            car.fire();
        });
        t2.start();
        t1.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void invokerObjectBlockMethod(){
        Car car = new Car();
        Thread t1 = new Thread(()->{
            car.race();
        });
        Thread t2 = new Thread(()->{
            car.fire();
        });
        t2.start();
        t1.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        String  line = null ;
        while (s.hasNextLine()) {
            line = s.next();
            if(line.equals("1")){
                // 两个方法都是 static synchronized 修饰
                invokerStaticMethod();
            }else if(line.equals("2")){
                // 对象调用 1 中的静态方法。
                invokerObjectMethod();
            }else if(line.equals("3")){
                // 一个调用对象方法，另外一个调用类方法
                invokerStaticAndObjectMethod();
            }else if(line.equals("4")){
                // 一个调用静态方法，另外一个调用方法块，此方法块是上多 Car Class 对象中的。
                invokerStaticBlock();
            }else if(line.equals("5")){
                // 一个修饰对象方法，另外一个是上到了修饰 this 的代码块
                invokerObjectBlockMethod();
            }else{
                break;
            }
        }
    }
}
